package com.xy.etl.kit;

import com.xy.core.constant.PingKit;
import com.xy.etl.ds.model.DataSourceConfig;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 各种缓存
 */
@Slf4j
public class ClientHelper {


    /**
     * 现场内缓存数据连接
     */
    private static Map<String, Map<String, Connection>> connectGroupMap = new HashMap<>();

    /**
     * 范围
     */
    private static ThreadLocal<String> clasz = new ThreadLocal<>();

    /**
     * 默认范围
     */
    private static String defaultValue = "ClientHelper";

    /**
     * 默认范围
     *
     * @return
     */
    public static String getDefault() {
        String scope = clasz.get();
        if (scope == null || scope.length() == 0) {
            scope = defaultValue;
        }
        return scope;
    }

    /**
     * 默认范围
     *
     * @return
     */
    public static void setDefault(String scope) {
        if (scope != null && scope.length() > 0) {
            clasz.set(scope);
        }
    }

    /**
     * 取得缓存
     *
     * @param clasz
     * @return
     */
    private static Map<String, Connection> getCache(String clasz) {
        Map<String, Connection> connectMap = connectGroupMap.get(clasz);
        if (connectMap == null) {
            connectMap = new HashMap<>();
            connectGroupMap.put(clasz, connectMap);
        }
        return connectMap;
    }

    /**
     * 检查连接
     *
     * @return
     */
    public synchronized static void checkConn() {
        checkConn(getDefault());
    }

    /**
     * 检查连接
     *
     * @return
     */
    public synchronized static void checkConn(String clasz) {
        List<String> keyList = new ArrayList<>();
        Map<String, Connection> connectMap = getCache(clasz);
        for (Map.Entry<String, Connection> entry : connectMap.entrySet()) {
            try {
                //检查空，是否关闭，是否有效
                if (entry.getValue() == null || entry.getValue().isClosed() || !entry.getValue().isValid(3000)) {
                    keyList.add(entry.getKey());
                }
            } catch (Exception ex) {
                log.error("检查连接未通过，异常：" + ex.getMessage());
                keyList.add(entry.getKey());
            }
        }
        if (keyList.size() > 0) {
            for (String key : keyList) {
                connectMap.remove(key);
            }
        }

    }

    /**
     * 取得连接
     *
     * @param configBean
     * @return
     */
    public synchronized static Connection getConn(DataSourceConfig configBean) throws Exception {
        return getConn(configBean, getDefault());
    }

    /**
     * 取得连接
     *
     * @param configBean
     * @return
     */
    public synchronized static Connection getConn(DataSourceConfig configBean, String clasz) throws Exception {
        //加载驱动
        Map<String, Connection> connectMap = getCache(clasz);
        Connection connection = connectMap.get(configBean.getUrl());
        if (connection == null || connection.isClosed()) {
            try {
                //异常旧数据
                connectMap.remove(configBean.getUrl());
                //测试ip
                String ip = PingKit.getIpFromUrl(configBean.getUrl());
                if (!PingKit.isOk(ip)) {
                    throw new Exception("网络地址" + ip + "不通，不能建立数据库链接");
                }
                log.info("ping 数据库 IP:" + ip + "...... 成功");
                //创建连接
                Class.forName(configBean.getDriver());
                log.info(configBean.getUrl() + "  " + configBean.getUsername());
                connection = DriverManager.getConnection(configBean.getUrl(), configBean.getUsername(), configBean.getPassword());
                connectMap.put(configBean.getUrl(), connection);
            } catch (Exception ex) {
                log.debug(ex.getMessage(), ex);
                log.error("取得数据库连接{}失败：{}", configBean.getUrl(), ex.getMessage());
                return null;
            }
        }
        return connection;
    }

    /**
     * 关闭连接
     *
     * @throws Exception
     */
    public static void clearConnection(DataSourceConfig configBean) {
        clearConnection(configBean, getDefault());
    }

    /**
     * 关闭连接
     *
     * @throws Exception
     */
    public static void clearConnection(DataSourceConfig configBean, String clasz) {
        try {
            Map<String, Connection> connectMap = getCache(clasz);
            Connection connection = connectMap.remove(configBean.getUrl());
            if (connection != null) {
                connection.close();
            }
        } catch (Exception ex) {
        }
    }
}
